package project.parser.ast.util;

import project.environments.StaticEnv;
import project.parser.TypecheckException;
import project.parser.ast.exps.Exp;
import project.parser.ast.types.RecordType;
import project.parser.ast.types.Type;

import static project.parser.ast.types.PrimType.BOOLEAN_TYPE;
import static project.parser.ast.types.PrimType.NUMBER_TYPE;

public class TypecheckUtil {
	private TypecheckUtil() {
	}

	private static void throwExcpetion(Type type, Exp e) { //eccezione di typechecking
		throw new TypecheckException("Expecting type " + type + " instead of '" + e.toString() + "'");
	}

	public static Type checkType(StaticEnv senv, Type type, Exp... exps) {
		for (Exp e : exps)
			if (e.typecheck(senv) != type)
				throwExcpetion(type, e);
		return type;
	}

	public static Type checkCompIntOp(StaticEnv senv, Exp e1, Exp e2) {
		if (e1.typecheck(senv) != NUMBER_TYPE || e2.typecheck(senv) != NUMBER_TYPE)
			throwExcpetion(NUMBER_TYPE, e2);
		return BOOLEAN_TYPE;
	}

	public static Type checkEqualOp(StaticEnv senv, Exp e1, Exp e2) { //check per espressioni di uguaglianza/disuguagliana
		Type leftType = e1.typecheck(senv);
		Type rightType = e2.typecheck(senv);
		if (leftType == NUMBER_TYPE && rightType != NUMBER_TYPE)
			throwExcpetion(NUMBER_TYPE, e2);
		if (leftType == BOOLEAN_TYPE && rightType != BOOLEAN_TYPE)
			throwExcpetion(BOOLEAN_TYPE, e2);
		if (RecordType.isInstance(leftType) && !RecordType.isInstance(rightType))
			throwExcpetion(new RecordType(null), e2);
		return BOOLEAN_TYPE;
	}
}
